#include<iostream>
#include"matrix.h"

using namespace math;
template<class Mat>
void output(const Mat& m)
{
//	std::cout <<" storage_size :" << m.storage_size() << std::endl;
//std::cout <<"& of data     :" << &m(0,0) << std::endl;
	for(auto i = 0; i < m.size1(); ++i)
	{
		for(auto j = 0; j < m.size2(); ++j)
			std::cout << m[i][j] << " ";
		std::cout <<std::endl;
	}
//	std::cout << std::endl;
}

template<class Mat>
void output2(const Mat& m)
{
	std::cout << "size()     :" << m.size() << "\n";
	std::cout << "size1()    :" << m.size1() << "\n";
	std::cout << "size2()    :" << m.size2() << "\n";
	std::cout << "empty()    :" << std::boolalpha << m.empty() << "\n\n";
}

int main()
{

	typedef matrix<double> Matrix;

	//default constructor
	std::cout << "1. default constructor:" << std::endl;
	Matrix m1;
	output(m1);
	output2(m1);

	//non-init fill constructor
	std::cout << "2. non-init fill constructor:" << std::endl;
	Matrix m2(4,3);
	output(m2);
	output2(m2);

	//init fill constructor
	std::cout << "3. non-init fill constructor:" << std::endl;
	Matrix m3(4,3,1);
	output(m3);
	output2(m3);

	//copy constructor
	std::cout << "4. copy constructor:" << std::endl;
	Matrix m4(m2);
	output(m4);
	output2(m4);

	//assignment	
	std::cout << "5. assignment:" << std::endl;
	m1 = m3;
	output(m1);
	output2(m1);

	std::cout << "6. +=, -=, *=, /=:" << std::endl;
	m1 *= matrix<int>(4,3,2.5);
	output(m1);
	output(m3);
	output2(m1);
	//


	//operator + - * /
	std::cout << "7. +, -, *, /:" << std::endl;
	output(m1 / m3 / m3);
	output(m1 / (m3 / m3));
	output((m1 / m1) / (m3 / m3));

	//move assignment
    std::cout << "8. move assignment:" << std::endl;
	m1 = m3 + m3;
	output(m1);
	output2(m1);

	//move constructor
	std::cout << "9. move constructor:" << std::endl;
	Matrix m5(m1 + m1 + m1);
	output(m5);

	//conversion
	std::cout << "10. conversion:" << std::endl;
	m5 = matrix<int>(4,3,2);
	output(m5);
	output2(m5);

	//swap
	std::cout << "11. swap:" << std::endl;
	Matrix m6;
	m6.swap(m5);
	output(m6);
	output2(m6);

	//negative
	std::cout << "12. negative:" << std::endl;
	output(-m6);
	output(-(m6 + m6));

	//negative
	std::cout << "13. + - * / scalar" << std::endl;
	output(m6 + 3);

}

